import { ref, unref, onMounted, onUnmounted } from "vue";
import { uploadSingle, uploadSingleHashName } from "@/api";
import { fileToBuffer } from "@/utils";

export function useUploadSingle({
  accept = ["png", "jpg"],
  multiple = false, // 是否支持多文件
  preview = false,
  isHashName = false,
  immediate = false,
  isProgress = false,
  fileMaxSize = 2 * 1024 * 1024, // 文件最大限制
} = {}) {
  // 上传文件框
  const inputRef = ref(null);
  const uploadRef = ref(null);
  const loading = ref(false);

  let filelist = ref([]); // 上次文件列表

  // 选择文件
  const selectFile = () => {
    if (unref(loading)) return;
    unref(inputRef)?.click(); // 触发文件选择框
  };

  // 文件选中
  const changeFile = () => {
    let files;
    // 多文件
    if (multiple) {
      files = [...unref(inputRef)?.files];
    } else {
      files = [unref(inputRef)?.files[0]];
    }
    handleUpload(files);
  };

  const handleUpload = (files) => {
    if (!files.length) return;
    let errList = []; // 收集不合要求文件
    let i = 0;
    while (i < files.length) {
      let file = files[i];
      // 文件类型限制
      if (!accept.some((item) => file.name?.indexOf(item) > -1)) {
        errList.push({ filename: file.name, type: "类型" });
      }
      // 大小限制
      if (file.size > fileMaxSize) {
        errList.push({ filename: file.name, type: "大小" });
      }
      i++;
    }
    // 去除不合格要求文件
    files = files.filter(
      (item) => !errList.find((er) => er.filename == item.name)
    );
    // 错误提示
    if (errList.length) {
      let str = handleError(errList);
      alert(str);
    }
    if (preview) {
      files = files.map((item) => ({
        file: item,
        url: URL.createObjectURL(item), // 创建图片预览地址
      }));
    } else {
      files = files.map((item) => ({ file: item }));
    }
    filelist.value = files;
    if (immediate) {
      uploadFile();
    }
  };

  // 上传文件
  const uploadFile = async () => {
    if (unref(loading)) return;
    if (!unref(filelist).length) {
      return alert("请选择文件");
    }
    loading.value = true; // 启动加载
    let max = 6; // 最大并发量
    let taskPool = [];
    let index = 0;
    for (let item of filelist.value) {
      index++;
      const formData = new FormData();
      formData.append("file", item.file);
      let task;
      if (isHashName) {
        let { filename } = await fileToBuffer(item.file); // 前端处理得到上传文件后的名字
        formData.append("filename", filename);
        task = uploadSingleHashName(formData, {
          onUploadProgress(ev) {
            let { loaded, total } = ev;
            if (isProgress) {
              item.progressLen = `${(loaded / total) * 100}%`;
            }
          },
        });
      } else {
        formData.append("filename", item.file.name);
        task = uploadSingle(formData, {
          onUploadProgress(ev) {
            let { loaded, total } = ev;
            if (isProgress) {
              item.progressLen = `${(loaded / total) * 100}%`;
            }
          },
        });
      }
      task.then((data) => {
        if (+data.code === 0) {
          taskPool.splice(
            taskPool.findIndex((item) => item == task),
            1
          );
        } else {
          return Promise.reject();
        }
      });
      taskPool.push(task);
      if (index === max) {
        await Promise.race(taskPool);
      }
    }
    Promise.all(taskPool)
      .then((res) => {
        res.forEach((item) => {
          if (+item.code === 0) {
            alert(
              `文件已经上传成功~~,您可以基于 ${item.servicePath} 访问这个资源~~`
            );
            return;
          }
          return Promise.reject(res.codeText);
        });
        // alert(`恭喜您文件都上传成功~~`);
      })
      .catch((err) => {
        console.log(err);
        alert("文件上传失败，请您稍后再试~~");
      })
      .finally(() => {
        filelist.value = [];
        loading.value = false;
      });
  };

  // 文件删除
  const deleteFile = (file) => {
    filelist.value = unref(filelist).filter((item) => item !== file);
  };

  function dragover(ev) {
    ev.preventDefault();
  }

  function drop(ev) {
    ev.preventDefault(); // 阻止默认事件
    let files;
    // 多文件
    if (multiple) {
      files = [...ev.dataTransfer?.files];
    } else {
      files = [ev.dataTransfer?.files[0]];
    }
    handleUpload(files);
  }

  // 挂载组件时
  onMounted(() => {
    uploadRef.value?.addEventListener("dragover", dragover);
    uploadRef.value?.addEventListener("drop", drop);
  });

  // 卸载组件时
  onUnmounted(() => {
    uploadRef.value?.removeEventListener("dragover", dragover);
    uploadRef.value?.removeEventListener("drop", drop);
  });

  return {
    uploadRef,
    inputRef,
    filelist,
    loading,
    selectFile,
    changeFile,
    uploadFile,
    deleteFile,
  };
}

// 处理错误
export function handleError(errList) {
  if (!errList.length) return;
  let error = {};
  errList.forEach((item) => {
    if (!error[item.filename]) {
      error[item.filename] = item.type;
    } else {
      error[item.filename] = error[item.filename] + "" + item.type;
    }
  });
  let errstr = "";
  for (let item in error) {
    errstr += "文件名 " + item + " " + error[item] + "不符合要求\t";
  }
  return errstr;
}
